home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 23 / AACD 23.iso / AACD / Online / opennap / public.c < prev    next >
C/C++ Source or Header  |  2001-06-08  |  7KB  |  260 lines

  1. /* Copyright (C) 2000-1 drscholl@users.sourceforge.net
  2.    This is free software distributed under the terms of the
  3.    GNU Public License.  See the file COPYING for details.
  4.  
  5.    $Id: public.c,v 1.41 2001/02/15 08:39:45 drscholl Exp $ */
  6.  
  7. #include <stdio.h>
  8. #ifndef WIN32
  9. #include <unistd.h>
  10. #endif
  11. #include <string.h>
  12. #include "opennap.h"
  13. #include "debug.h"
  14.  
  15. /* static buffer for use by public/emote.  these get called a lot so speed
  16.    things up by keeping it around.  there is no chance of either of these
  17.    being called from eachother or used elsewhere so this is safe */
  18. static char PublicBuf[2048];
  19.  
  20. /* determine if `sender' has permission to send to channel `chan' */
  21. static int
  22. check_permission (CHANNEL * chan, USER * sender)
  23. {
  24.     LIST   *list;
  25.     CHANUSER *chanUser;
  26.  
  27.     for (list = chan->users; list; list = list->next)
  28.     {
  29.     chanUser = list->data;
  30.     if (chanUser->user == sender)
  31.         break;
  32.     }
  33.  
  34.     if (!list)
  35.     {
  36.     log ("check_permission: fatal error, could not find %s on channel %s",
  37.          sender->nick, chan->name);
  38.     return -1;
  39.     }
  40.  
  41.     if (sender->level < LEVEL_MODERATOR
  42.     && (chanUser->flags & ON_CHANNEL_OPERATOR) == 0)
  43.     {
  44.     if (chan->flags & ON_CHANNEL_MODERATED)
  45.     {
  46.         if ((chanUser->flags & ON_CHANNEL_VOICE) == 0)
  47.         {
  48.         if (ISUSER (sender->con))
  49.             send_cmd (sender->con, MSG_SERVER_NOSUCH,
  50.                   "permission denied: channel is moderated");
  51.         return -1;
  52.         }
  53.     }
  54.     else if (chanUser->flags & ON_CHANNEL_MUZZLED)
  55.     {
  56.         if (ISUSER (sender->con))
  57.         send_cmd (sender->con, MSG_SERVER_NOSUCH,
  58.               "permission denied: muzzled on channel");
  59.         return -1;
  60.     }
  61.     }
  62.  
  63.     return 0;
  64. }
  65.  
  66. /* 402 [ :<sender> ] <channel> <text> */
  67. /*  public message to a channel */
  68. HANDLER (public)
  69. {
  70.     CHANNEL *chan;
  71.     USER   *sender;
  72.     LIST   *list;
  73.     char   *ptr;
  74.     char   *sender_name;
  75.     CHANUSER *chanUser;
  76.  
  77.     ASSERT (validate_connection (con));
  78.     /* save the starting position of the pkt */
  79.     ptr = pkt;
  80.     if (pop_user_server (con, tag, &pkt, &sender_name, &sender))
  81.     return;
  82.     if (sender->muzzled)
  83.     {
  84.     if (ISUSER (con))
  85.         send_cmd (con, MSG_SERVER_NOSUCH, "You are muzzled.");
  86.     return;
  87.     }
  88.  
  89.     /* protect against DoS attack against the windows napster client */
  90.     if (len - (pkt - ptr) > 180)
  91.     {
  92.     pkt[180] = 0;        /* crop the message */
  93.     log ("public: cropped %d byte message from user %s", len,
  94.          sender->nick);
  95.     }
  96.  
  97.     /* can't use split line here because the text field is considered all
  98.        one item */
  99.     /* extract the channel name. NOTE: we don't use next_arg() here because
  100.        it will strip leading space from the text being sent */
  101.     ptr = next_arg_noskip (&pkt);
  102.     if (!pkt)
  103.     {
  104.     unparsable (con);
  105.     return;
  106.     }
  107.  
  108.     /* find the channel this message is going to. look the user's joined
  109.        channels since this should be faster than lookup in the hash table */
  110.     if (!(chan = find_channel (sender->channels, ptr)))
  111.     {
  112.     if (ISUSER (con))
  113.         send_cmd (con, MSG_SERVER_NOSUCH,
  114.               "You are not a member of that channel");
  115.     return;
  116.     }
  117.  
  118.     if (ISSERVER (con) && chan->local)
  119.     {
  120.     log ("public: server %s accessed local channel %s", con->host,
  121.          chan->name);
  122.     return;
  123.     }
  124.  
  125.     if (check_permission (chan, sender))
  126.     return;
  127.  
  128.     /* relay this message to peer servers */
  129.     if (!chan->local)
  130.     pass_message_args (con, tag, ":%s %s %s", sender->nick, chan->name,
  131.                pkt);
  132.  
  133.     /* the majority of the users in the channel will see this message, so
  134.        form it one time */
  135.     len = form_message (PublicBuf, sizeof (PublicBuf), MSG_SERVER_PUBLIC,
  136.             "%s %s %s", chan->name,
  137.             sender->cloaked ? "Operator" : sender->nick, pkt);
  138.  
  139.     /* send this message to everyone in the channel */
  140.     for (list = chan->users; list; list = list->next)
  141.     {
  142.     chanUser = list->data;
  143.     ASSERT (chanUser->magic == MAGIC_CHANUSER);
  144.     if (ISUSER (chanUser->user->con))
  145.     {
  146.         if (sender->cloaked && chanUser->user->level > LEVEL_USER)
  147.         send_cmd (chanUser->user->con, MSG_SERVER_PUBLIC, "%s %s %s",
  148.               chan->name, sender->nick, pkt);
  149.         else
  150.         queue_data (chanUser->user->con, PublicBuf, len);
  151.     }
  152.     }
  153. }
  154.  
  155. /* 824 [ :<user> ] <channel> "<text>" */
  156. HANDLER (emote)
  157. {
  158.     CHANUSER *chanUser;
  159.     USER   *user;
  160.     CHANNEL *chan;
  161.     char   *ptr, *av[2];
  162.     char   *sender_name;
  163.     LIST   *list;
  164.  
  165.     ASSERT (validate_connection (con));
  166.     ptr = pkt;            /* save initial location */
  167.     if (pop_user_server (con, tag, &pkt, &sender_name, &user) != 0)
  168.     return;
  169.     if (user->muzzled)
  170.     {
  171.     if (ISUSER (con))
  172.         send_cmd (con, MSG_SERVER_NOSUCH, "You are muzzled");
  173.     return;
  174.     }
  175.  
  176.     /* protect against DoS attack against the windows napster client */
  177.     if (len - (pkt - ptr) > 180)
  178.     {
  179.     /* crop message */
  180.     pkt[179] = '"';
  181.     pkt[180] = 0;
  182.     log ("emote: cropped %d byte message from user %s", len, user->nick);
  183.     }
  184.  
  185.     if (split_line (av, sizeof (av) / sizeof (char *), pkt) < 2)
  186.     {
  187.     unparsable (con);
  188.     return;
  189.     }
  190.  
  191.     /* find the channel this message is going to. look the user's joined
  192.        channels since this should be faster than lookup in the hash table */
  193.     if (!(chan = find_channel (user->channels, av[0])))
  194.     {
  195.     if (ISUSER (con))
  196.         send_cmd (con, MSG_SERVER_NOSUCH,
  197.               "You are not a member of that channel");
  198.     return;
  199.     }
  200.  
  201.     if (ISSERVER (con) && chan->local)
  202.     {
  203.     log ("emote: server %s accessed local channel %s",
  204.          con->host, chan->name);
  205.     return;
  206.     }
  207.  
  208.     if (check_permission (chan, user))
  209.     return;
  210.  
  211.     /* relay to peer servers */
  212.     if (!chan->local)
  213.     pass_message_args (con, tag, ":%s %s \"%s\"", user->nick, chan->name,
  214.                av[1]);
  215.  
  216.     /* majority of the users see the same message, so form it once */
  217.     len = form_message (PublicBuf, sizeof (PublicBuf), tag, "%s %s \"%s\"",
  218.             chan->name,
  219.             user->cloaked ? "Operator" : user->nick, av[1]);
  220.  
  221.     /* send this message to all channel members */
  222.     for (list = chan->users; list; list = list->next)
  223.     {
  224.     chanUser = list->data;
  225.     ASSERT (chanUser->magic == MAGIC_CHANUSER);
  226.     if (ISUSER (chanUser->user->con))
  227.     {
  228.         if (user->cloaked && chanUser->user->level > LEVEL_USER)
  229.         send_cmd (chanUser->user->con, tag, "%s %s \"%s\"",
  230.               chan->name, user->nick, av[1]);
  231.         else
  232.         queue_data (chanUser->user->con, PublicBuf, len);
  233.     }
  234.     }
  235. }
  236.  
  237. /* queues a raw message (tag & length header is assumed to be present */
  238. int
  239. send_to_channel (char *name, char *buf, int buflen)
  240. {
  241.     CHANNEL *chan;
  242.     LIST   *list;
  243.     CHANUSER *user;
  244.  
  245.     /* if the Channels hash table has not been initialized yet, abort */
  246.     if (!Channels)
  247.     return -1;
  248.     chan = hash_lookup (Channels, name);
  249.     /* if nobody is in the log channel, abort */
  250.     if (!chan)
  251.     return -1;
  252.     for (list = chan->users; list; list = list->next)
  253.     {
  254.     user = list->data;
  255.     if (ISUSER (user->user->con))
  256.         queue_data (user->user->con, buf, buflen);
  257.     }
  258.     return 0;
  259. }
  260.